.. :validated: 3.2.0

.. _usin_block_user_replic_agr:

Настройка репликации блокировки пользователя по паролю
======================================================

Введение
--------

Включение атрибутов, реализующих механизм учёта неудачных попыток входа, в список репликации между контроллерами может привести к нестабильному и непредсказуемому поведению системы, так как эти атрибуты изменяются на том сервере, на который поступает запрос на аутентификацию. Основной риск заключается в конкуренции данных при репликации. Если атрибут включен в репликацию, его изменение на одном сервере будет перезаписывать значение на другом. Поскольку попытки входа (как успешные, так и нет) могут происходить на разных репликах практически одновременно, это приводит к "гонке" данных. Например, до окончания полной репликации с сервера А на сервер В может быть сделана более поздняя неудачная попытка входа и значение атрибута станет 3, в то время как на сервере А уже было зафиксировано 5 попыток. Это приведет к репликации значения с сервера В на сервера А и откату значения на сервере А на более новое, но неверное. Такая конкуренция делает данные ненадёжными, может нарушить логику блокировки учётных записей и создать избыточную нагрузку на службу репликации. Архитектурно надёжнее вынести функционал принятия решения о блокировке учётной записи во внешнюю систему аудита.

Частые изменения атрибутов приводят к увеличению нагрузки на сервер и службу репликации. Характер нагрузки зависит от конкретной инфраструктуры, распределения аутентификационных запросов и количества реплик. На практике основное влияние приходится на дисковую подсистему, тогда как потребление CPU, памяти и сетевых ресурсов растёт незначительно. В одном из тестовых сценариев применение решения увеличило дисковую нагрузку примерно на 30%. В реальных условиях производительность системы зависит от оборудования клиента и требует тестирования на месте.

Настоятельно рекомендуется не включать эти атрибуты в репликацию без крайней необходимости и чёткого понимания рисков.

Репликация блокировки пользователя при превышении числа неудачных попыток обеспечивает запрет аутентификации на всех контроллерах домена в инфраструктуре предприятия. Для принятия решения о блокировке пользователя при превышении числа неудачных попыток аутентификации используются атрибуты ``krbloginfailedcount`` (количество неудачных попыток входа) и ``krblastfailedauth`` (время последней неудачной аутентификации). Так как атрибуты изначально находятся в списке **EXCLUDE**, т.е. исключены из соглашения о репликации, то применение данной инструкции позволит добавить их в репликацию. Список **EXCLUDE** задается в следующих исходных файлах **FreeIPA** через переменные:

* */usr/lib/python3/dist-packages/ipalib/constants.py*,
* */usr/lib/python3/dist-packages/ipaserver/install/replication.py*.

На основании этих переменных заполняется шаблон соглашений о репликации в **DN**:
``cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan``
и сами соглашения о репликации в **DN**:
``cn=replica,cn=dc\3Dald\2Cdc\3Dcompany\2Cdc\3Dcom,cn=mapping tree,cn=config``.

.. note::

   В инструкции используются примеры команд, где **DN** содержит имя тестового домена. При использовании примеров из инструкций **DN** должен включать имя реального домена, с которым производятся действия.

Списки **EXCLUDE** значений атрибутов репликации по умолчанию:

.. code-block:: bash

   nsDS5ReplicatedAttributeList: (objectclass=*)$ EXCLUDE memberof idnssoaserial  entryusn krblastsuccessfulauth krblastfailedauth krbloginfailedcount
   nsDS5ReplicatedAttributeListTotal: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth krblastfailedauth krbloginfailedcount

- ``nsDS5ReplicatedAttributeList`` - список атрибутов LDAP-объектов, которые реплицируются между КД в рамках конкретного соглашения о репликации;
- ``nsDS5ReplicatedAttributeListTotal`` - расширенный список атрибутов, со всеми атрибутами, которые должны реплицироваться, включая служебные и дополнительные. Используется для полного контроля репликации.

Списки **EXCLUDE** задаются через следующие переменные:

.. code-block:: bash

   # List of attributes that need to be excluded from replication initialization.
   TOTAL_EXCLUDES = ('entryusn',
                   'krblastsuccessfulauth',
                    'krblastfailedauth',
                    'krbloginfailedcount')
   # List of attributes that need to be excluded from normal replication.
   EXCLUDES = ('memberof', 'idnssoaserial') + TOTAL_EXCLUDES

Получить билет **kerberos**:

.. code-block:: bash

   kinit admin

Проверять значения атрибутов неудачных попыток авторизации пользователя на всех контроллерах домена можно командой:

.. code-block:: bash

   ipa user-status <ИМЯ ПОЛЬЗОВАТЕЛЯ>

Пример ответа:

.. code-block:: bash

   -----------------------
   Account disabled: False
   -----------------------
     Сервер: dc01.ald.company.lan
     Неудачные попытки входа: 0
     Последняя успешная аутентификация: 2025-07-24T14:18:53Z
     Последняя ошибка при аутентификации: 2025-07-17T11:35:14Z
     Время сейчас: 2025-07-24T14:18:53Z

     Сервер: dc02.ald.company.lan
     Неудачные попытки входа: 0
     Последняя успешная аутентификация: 2025-07-24T14:18:53Z
     Последняя ошибка при аутентификации: 2025-07-17T11:35:14Z
     Время сейчас: 2025-07-24T14:18:53Z
   ---------------------------------
   Количество возвращённых записей 2
   ---------------------------------

.. attention::

   Рекомендуется создать резервную копию каталога перед изменением.

Область применения
------------------

Данная инструкция в полном объеме актуальна для стека под управлением **ALD Pro** с развернутыми КД и подсистемами с установленной **ОС Astra Linux**, соответствующим требованиям **Матрице совместимости** в **Руководстве Администратора. Часть 1**.

Исключение расхождения данных
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Чтобы избежать несогласованности данных, когда актуальными считаются значения атрибутов на новом контроллере домена из-за возможной неудачной попытки аутентификации пользователя на нём (что после репликации приводит к удалению актуальной информации о неудачных попытках аутентификации), рекомендуется временно сделать реплику на новом КД скрытой (``hidden``) сразу после инсталляции.

.. code-block:: bash

   ipa server-state <ИМЯ КОНТРОЛЛЕРА ДОМЕНА> --state=hidden

После исправления соглашения о репликации и переинициализации контроллера, его необходимо вернуть в обычное состояние следующей командой:

.. code-block:: bash

   ipa server-state <ИМЯ КОНТРОЛЛЕРА ДОМЕНА> --state=enabled

Настройка в инфраструктуре на действующих контроллерах домена
-------------------------------------------------------------

Прежде чем приступить к настройке, необходимо посмотреть список атрибутов, которые участвуют в репликации, чтобы убедиться в том, что есть необходимость применения данной инструкции.

Пример команды:

.. code-block:: bash

   ldapsearch -x -D "cn=Directory Manager" -W -b "cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan" nsDS5ReplicatedAttributeList nsDS5ReplicatedAttributeListTotal

Пример полученного ответа приведен во введении, где значение ``(objectclass=*)$ EXCLUDE`` означает, что в репликацию включаются все атрибуты объектов ``(objectclass=)``, кроме перечисленных после **EXCLUDE**.

Перед внесением изменений необходимо обеспечить консистентность значений этих атрибутов путем удаления их для всех пользователей на всех контроллерах домена.

.. attention::

   Так как требования информационной безопасности у каждой организации разные, это может противоречить политике безопасности компании.

В зависимости от масштаба инфраструктуры организации, удалить атрибуты необходимо у каждого пользователя по отдельности вручную или прибегнуть к частичной автоматизации для массового процесса удаления.

Удаление атрибутов у пользователя
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Перед удалением атрибутов необходимо получить список всех пользователей с атрибутами на конкретном контроллере домена:

.. code-block:: bash

   ldapsearch -x -D "cn=Directory Manager" -W -b "cn=users,cn=accounts,dc=ald,dc=company,dc=lan" "(&(objectClass=person)(|(krbloginfailedcount=*)(krblastfailedauth=*)))" dn krbloginfailedcount krblastfailedauth

Фильтр ищет **DN** пользователя в виде ``uid=user1,cn=users,cn=accounts,dc=ald,dc=company,dc=lan``, у которых есть хотя бы один из указанных атрибутов. После получения списка, необходимо удалить атрибуты у каждого пользователя.

Для удаления атрибутов у пользователя на конкретном КД необходимо использовать команду:

.. code-block:: bash

   ldapmodify -x -D "cn=Directory Manager" -W -h ldap://dc01.ald.company.lan -p 389
   dn: uid=user1,cn=users,cn=accounts,dc=ald,dc=company,dc=lan
   changetype: modify
   delete: krbloginfailedcount
   -
   delete: krblastfailedauth
   -

.. _usin_block_user_replic_agr_changes:

Внесение изменений в соглашения о репликации
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Перед внесением изменений необходимо получить список всех соглашений о репликации командой:

.. code-block:: bash

   ipa topologysegment-find domain --pkey-only

- ключ ``--pkey-only`` означает, что результаты должны содержать только атрибут первичного ключа, и вывести список всех соглашений в виде:

.. code-block:: bash

   ------------------
   найдено 1 сегмента
   ------------------
     Имя сегмента: dc01.ald.company.lan-to-dc02.ald.company.lan
   ---------------------------------
   Количество возвращённых записей 1
   ---------------------------------

В данном примере продемонстрирован один сегмент, но на практике изменения необходимо вносить для каждого сегмента.

.. attention::

   Если в список атрибутов для исключения из репликации ранее были внесены дополнительные изменения и текущий список отличается от списка по умолчанию (на примере которого написана инструкция), то изменения в список необходимо вносить с учётом сделанных ранее изменений.

Вносить изменения во все действующие сегменты соглашений о репликации можно на одном выделенном КД с помощью команды:

.. code-block:: bash

   ipa topologysegment-mod domain dc01.ald.company.lan-to-dc02.ald.company.lan --replattrs "(objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth"

- параметр ``--replattrs`` позволяет изменить в сегменте список атрибутов, которые не реплицируются на сервер-потребитель при **частичном** обновлении.

.. code-block:: bash

   --------------------------------------------------------------
   Изменён сегмент "dc01.ald.company.lan-to-dc02.ald.company.lan"
   --------------------------------------------------------------
     Имя сегмента: dc01.ald.company.lan-to-dc02.ald.company.lan
     Левый узел: dc01.ald.company.lan
     Правый узел: dc02.ald.company.lan
     Возможность подключения: both
     Attributes to replicate: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth

.. code-block:: bash

   ipa topologysegment-mod domain dc01.ald.company.lan-to-dc02.ald.company.lan --replattrstotal "(objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth"

- параметр ``--replattrstotal`` позволяет изменить в сегменте список атрибутов, которые не реплицируются на сервер-потребитель при **полном** обновлении (реинициализации).

.. code-block:: bash

   --------------------------------------------------------------
   Изменён сегмент "dc01.ald.company.lan-to-dc02.ald.company.lan"
   --------------------------------------------------------------
     Имя сегмента: dc01.ald.company.lan-to-dc02.ald.company.lan
     Левый узел: dc01.ald.company.lan
     Правый узел: dc02.ald.company.lan
     Возможность подключения: both
     Attributes to replicate: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth
     Атрибуты для общего обновления: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth

Внесение изменений в шаблон репликации
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. note::
    
   При добавлении нового соглашения между существующими КД дополнительных действий не требуется, поскольку будут применены значения шаблона репликации, который также должен содержать исправленный список атрибутов.

Для включения изменений в новые соглашения о репликации, создаваемых на основе шаблона в действующей инфраструктуре, необходимо убрать в шаблоне репликации из списка исключений **EXCLUDE** атрибуты ``nsDS5ReplicatedAttributeList`` и ``nsDS5ReplicatedAttributeListTotal`` командой ``ldapmodify``, предварительно создав файл *.ldif* с помощью которого будут внесены изменения.

Для создания файла необходимо в командной строке выполнить команду:

.. code-block:: bash

   nano /<ПУТЬ К ДИРЕКТОРИИ>/change-domain.ldif

Заполнить файл *.ldif*, в котором **DN** должен соответствовать домену, где необходимо внести изменения, и сохранить его:

.. code-block:: bash

   dn: cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   changetype: modify
   replace: nsDS5ReplicatedAttributeList
   nsDS5ReplicatedAttributeList: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth
   -
   replace: nsDS5ReplicatedAttributeListTotal
   nsDS5ReplicatedAttributeListTotal: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth

После создания файла необходимо внести изменения с помощью команды:

.. code-block:: bash

   ldapmodify -W -D "cn=Directory Manager" -f /<ПУТЬ К ДИРЕКТОРИИ>/change-domain.ldif

Ответ о принятых изменениях:

.. code-block:: bash

   modifying entry "cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan

Настройка в инфраструктуре после добавления нового контроллера домена
---------------------------------------------------------------------

Исправление соглашения о репликации с новым КД
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Поскольку при продвижении сервера до роли КД создаваемое соглашение о репликации будет содержать список атрибутов из установочного файла, то необходимо исправить новое созданное соглашение о репликации между новым и центральным контроллерами.

Команды и ответы аналогичны :ref:`usin_block_user_replic_agr_changes`, но выполняются только для соглашения о репликации с новым КД.

Команда исправления соглашения о репликации с параметром ``--replattrs``:

.. code-block:: bash
    
   ipa topologysegment-mod domain dc01.ald.company.lan-to-dc03.ald.company.lan --replattrs "(objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth"

Команда исправления соглашения о репликации с параметром ``--replattrstotal``:

.. code-block:: bash

   ipa topologysegment-mod domain dc01.ald.company.lan-to-dc03.ald.company.lan --replattrstotal "(objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth"

Реинициализирование нового контроллера домена
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Так как при продвижения сервера до роли КД и первоначальной инициализации каталога **LDAP** нужные атрибуты не были реплицированы из-за списка **EXCLUDE** по умолчанию, то необходимо реинициализировать контроллер после исправления соглашения о репликации командой с соответствующим ключом:

.. code-block:: bash

   ipa topologysegment-reinitialize domain dc01.ald.company.lan-to-dc03.ald.company.lan --right

- ``--right`` - указывает, что инициализировать необходимо "правый" контроллер,
- ``--left`` - указывает, что инициализировать необходимо "левый" контроллер.

Удаление в шаблоне репликации вторых дополнительных значений
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Поскольку значения по умолчанию для списка **EXCLUDE** отличаются от действующих, то подсистема создания контроллера домена добавляет в **LDAP** эти "лишние" значения. По этому в шаблоне репликации необходимо удалить вторые дополнительные значения параметров ``nsDS5ReplicatedAttributeList`` и ``nsDS5ReplicatedAttributeListTotal``.

Чтобы удалить значения необходимо создать *.ldif* файл и применить изменения с помощью команды ``ldapmodify``.

Перед созданием файла *.ldif* необходимо проверить текущее значение:

.. code-block:: bash

   ldapsearch -x -D "cn=Directory Manager" -W -b "cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan" nsDS5ReplicatedAttributeList nsDS5ReplicatedAttributeListTotal

В ответе видны вторые дополнительные значения ``nsDS5ReplicatedAttributeList`` и ``nsDS5ReplicatedAttributeListTotal`` которые необходимо удалить:

.. code-block:: bash

   ldapsearch -x -D "cn=Directory Manager" -W -b "cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan" "(objectclass=*)" nsDS5ReplicatedAttributeList nsDS5ReplicatedAttributeListTotal
   Enter LDAP Password:
   # extended LDIF
   #
   # LDAPv3
   # base <cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan> with scope subtree
   # filter: (objectclass=*)
   # requesting: nsDS5ReplicatedAttributeList nsDS5ReplicatedAttributeListTotal
   #
   
   # topology, ipa, etc, ald.company.lan
   dn: cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   
   # domain, topology, ipa, etc, ald.company.lan
   dn: cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   nsDS5ReplicatedAttributeList: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth
   nsDS5ReplicatedAttributeList: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth krblastfailedauth krbloginfailedcount
   nsDS5ReplicatedAttributeListTotal: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth
   nsDS5ReplicatedAttributeListTotal: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth krblastfailedauth krbloginfailedcount
   
   # dc01.ald.company.lan-to-dc03.ald.company.lan, domain, topology, ipa, etc, ald.company.lan
   dn: cn=dc01.ald.company.lan-to-dc03.ald.company.lan,cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   nsDS5ReplicatedAttributeList: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth
   nsDS5ReplicatedAttributeListTotal: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth

Далее создать файл *.ldif*:

.. code-block:: bash

    nano /<ПУТЬ К ДИРЕКТОРИИ>/delete_krbloginfailed.ldif

Заполнить файл, в котором **DN** должен соответствовать домену, где необходимо внести изменения, и сохранить его:

.. code-block:: bash

   dn: cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   changetype: modify
   delete: nsDS5ReplicatedAttributeList
   nsDS5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth krblastfailedauth krbloginfailedcount
   -
   delete: nsDS5ReplicatedAttributeListTotal
   nsDS5ReplicatedAttributeListTotal: (objectclass=*) $ EXCLUDE entryusn krblastsuccessfulauth krblastfailedauth krbloginfailedcount
   -

Внести изменения командой ``ldapmodify``:

.. code-block:: bash

   ldapmodify -x -D "cn=Directory Manager" -W -f /<ПУТЬ К ДИРЕКТОРИИ>/delete_krbloginfailed.ldif
   Enter LDAP Password:
   modifying entry "cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan"

Проверить результат с помощью ``ldapsearh``:

.. code-block:: bash
   
   astra@dc02:~$ ldapsearch -x -D "cn=Directory Manager" -W   -b "cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan" nsDS5ReplicatedAttributeList nsDS5ReplicatedAttributeListTotal
   Enter LDAP Password:
   # extended LDIF
   #
   # LDAPv3
   # base <cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan> with scope subtree
   # filter: (objectclass=*)
   # requesting: nsDS5ReplicatedAttributeList nsDS5ReplicatedAttributeListTotal
   
   # topology, ipa, etc, ald.company.lan
   dn: cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   
   # domain, topology, ipa, etc, ald.company.lan
   dn: cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   nsDS5ReplicatedAttributeList: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth
   nsDS5ReplicatedAttributeListTotal: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth
   
   # dc01.ald.company.lan-to-dc03.ald.company.lan, domain, topology, ipa, etc, ald.company.lan
   dn: cn=dc01.ald.company.lan-to-dc02.ald.company.lan,cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan
   nsDS5ReplicatedAttributeList: (objectclass=*)$ EXCLUDE memberof idnssoaserial entryusn krblastsuccessfulauth
   nsDS5ReplicatedAttributeListTotal: (objectclass=*)$ EXCLUDE entryusn krblastsuccessfulauth
